package com.cata.mall.security.component;

import com.cata.mall.security.util.JwtTokenUtil;
import lombok.NonNull;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * @作者: Tao
 * @日期: 2025/10/11
 * @时间: 11:19
 * @描述: JWT登录授权过滤器<pre>
 */
public class JwtAuthenticationTokenFilter extends OncePerRequestFilter {
    private static final Logger LOGGER = LoggerFactory.getLogger(JwtAuthenticationTokenFilter.class);
    @Autowired
    private UserDetailsService userDetailsService;
    @Autowired
    private JwtTokenUtil jwtTokenUtil;
    @Value("${jwt.tokenHeader}")
    private String tokenHeader;
    @Value("${jwt.tokenHead}")
    private String tokenHead;

    /**
     * 执行JWT认证过滤器的内部逻辑
     * 该方法从请求头中提取JWT令牌，验证令牌有效性，并设置Spring Security的认证信息
     *
     * @param request HttpServletRequest对象，包含客户端的请求信息
     * @param response HttpServletResponse对象，用于向客户端发送响应
     * @param filterChain FilterChain对象，用于继续执行过滤器链中的下一个过滤器
     * @throws ServletException 当Servlet处理过程中发生错误时抛出
     * @throws IOException 当输入输出操作发生错误时抛出
     */
    @Override
    protected void doFilterInternal(HttpServletRequest request, @NonNull HttpServletResponse response, @NonNull FilterChain filterChain) throws ServletException, IOException {
        // 从请求头中获取认证信息
        String authHeader = request.getHeader(this.tokenHeader);
        if (authHeader != null && authHeader.startsWith(this.tokenHead)) {
            // 提取JWT令牌（去除"Bearer "前缀）
            String authToken = authHeader.substring(this.tokenHead.length());// The part after "Bearer "
            // 从JWT令牌中解析用户名
            String username = jwtTokenUtil.getUserNameFromToken(authToken);
            LOGGER.info("checking username:{}", username);
            // 如果用户名存在且当前没有认证信息，则进行认证验证
            if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {
                // 根据用户名加载用户详细信息
                UserDetails userDetails = this.userDetailsService.loadUserByUsername(username);
                // 验证JWT令牌是否有效
                if (jwtTokenUtil.validateToken(authToken, userDetails)) {
                    // 创建认证对象并设置认证信息
                    UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
                    authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
                    LOGGER.info("authenticated user:{}", username);
                    SecurityContextHolder.getContext().setAuthentication(authentication);
                }
            }
        }
        // 继续执行过滤器链
        filterChain.doFilter(request, response);
    }

}
